/*
 * InGameNormalModeArcade.cpp
 *
 *  Created on: 2011-03-29
 *      Author: lpieczkowski
 */

#include <FGraphics.h>
#include <FGraphicsOpengl.h>

#include <Screens/InGameNormalModeArcade.h>
#include <Vertex/InGameNormalModeArcade.v>
#include <Callbacks/InGameNormalModeArcade.h>
#include <Menu/Menu.h>

using namespace Osp::Graphics::Opengl;
using namespace Osp::Base;
using namespace Osp::Base::Utility;
using namespace Osp::Graphics;
using namespace Osp::Media;
using namespace Osp::Base::Runtime;

InGameNormalModeArcade::InGameNormalModeArcade()
{

}

InGameNormalModeArcade::~InGameNormalModeArcade()
{

}

void InGameNormalModeArcade::Initialize(void)
{
	transX = 0;
	transBoundariesX = 0;
	direction = DIR_RIGHT;
	LineSpeed = 0.02f;
	needsNextBoundaries = false;

	LoadTextures();
	GenerateParticles();

	lightnings = new Lightning(2.0f);

	AppLog("After INIT");
}

void InGameNormalModeArcade::GenerateParticles(void)
{
	for(int i = 0; i < VERTICAL_PARTICLE_COUNT; i++)
		for(int j = 0; j < HORIZONTAL_PARTICLE_COUNT; j++)
		{
			particles[i][j] = new Particle();

			particles[i][j]->generateParams();

			particles[i][j]->x = j * (BOUNDARY_WIDTH / HORIZONTAL_PARTICLE_COUNT);
			particles[i][j]->y = i * (BOUNDARY_HEIGHT / VERTICAL_PARTICLE_COUNT);
			particles[i][j]->width = (BOUNDARY_WIDTH / HORIZONTAL_PARTICLE_COUNT);
			particles[i][j]->height = (BOUNDARY_HEIGHT / VERTICAL_PARTICLE_COUNT);

			//Create particle vertex array
			particles[i][j]->vertArray[0] = particles[i][j]->x;
			particles[i][j]->vertArray[1] = particles[i][j]->y;

			particles[i][j]->vertArray[2] = particles[i][j]->x;
			particles[i][j]->vertArray[3] = particles[i][j]->y + particles[i][j]->height;

			particles[i][j]->vertArray[4] = particles[i][j]->x + particles[i][j]->width;
			particles[i][j]->vertArray[5] = particles[i][j]->y;

			particles[i][j]->vertArray[6] = particles[i][j]->x + particles[i][j]->width;
			particles[i][j]->vertArray[7] = particles[i][j]->y + particles[i][j]->height;


			//Create particle texture coordinate array
			particles[i][j]->texCoords[0] = (float)j * (1.0f / float(HORIZONTAL_PARTICLE_COUNT));
			particles[i][j]->texCoords[1] = 1.0f - ((1.0f / (float)VERTICAL_PARTICLE_COUNT) * ((float)i + 1.0f));

			particles[i][j]->texCoords[2] = particles[i][j]->texCoords[0];
			particles[i][j]->texCoords[3] = particles[i][j]->texCoords[1] + (1.0f / (float)VERTICAL_PARTICLE_COUNT);

			particles[i][j]->texCoords[4] = particles[i][j]->texCoords[0] + (1.0f / (float)HORIZONTAL_PARTICLE_COUNT);
			particles[i][j]->texCoords[5] = particles[i][j]->texCoords[1];

			particles[i][j]->texCoords[6] = particles[i][j]->texCoords[4];
			particles[i][j]->texCoords[7] = particles[i][j]->texCoords[3];

			//AppLog("[%i][%i] [%f][%f]", i, j, particles[i][j].texCoords[6], particles[i][j].texCoords[7]);
		}
	AppLog("After init particles");
}

void InGameNormalModeArcade::LoadTextures()
{
	HitTheLines::LoadTexture(L"/Res/Bound.png", &lineTexture);
	HitTheLines::LoadTexture(L"/Res/LineGradient.png", &lineGradientTexture);
}

void InGameNormalModeArcade::UpdateLogic(void)
{
	switch (direction)
	{
	case DIR_LEFT:
		transX -= LineSpeed;
		break;
	case DIR_RIGHT:
		transX += LineSpeed;
		break;
	default:
		break;
	}

	if (transX >= 1) {
		direction = DIR_LEFT;
	} else if (transX <= -1) {
		direction = DIR_RIGHT;
	}

	if (needsNextBoundaries) {
		//Collision check:
		if ((transX > transBoundariesX - 0.1) && (transX < transBoundariesX	+ 0.1)) {
			AppLog("MATCH");

			for(int i = 0; i < VERTICAL_PARTICLE_COUNT; i++)
				for(int j = 0; j < HORIZONTAL_PARTICLE_COUNT; j++)
				{
					particles[i][j]->Reset();
					particles[i][j]->generateParams();
				}

			oldTransBoundariesX = transBoundariesX;
			//New boundaries calculation
			transBoundariesX = (GLfloat) (Math::Rand() % 100);
			if (transBoundariesX > 50)
			{
				transBoundariesX = (100 - transBoundariesX) * 0.02;
			}
			else
			{
				transBoundariesX *= -0.02;
			}

			//boundary range check:
			if (transBoundariesX > 0.9)
				transBoundariesX = 0.9;
			else if (transBoundariesX < -0.9)
				transBoundariesX = -0.9;

			// Increase speed
			LineSpeed += 0.001;

		} else //reset variables
		{
			AppLog("NO MATCH");
			transBoundariesX = 0;
			LineSpeed = 0.02;
			transX = 0;
			HitTheLines::getInstance()->Vibrator.Stop();
			HitTheLines::getInstance()->Vibrator.Start(500);
		}
		needsNextBoundaries = false;
	}

	for(int i = 0; i < VERTICAL_PARTICLE_COUNT; i++)
		for(int j = 0; j < HORIZONTAL_PARTICLE_COUNT; j++)
		{
			if(particles[i][j]->life)
			{
				long long ticks;
				Osp::System::SystemTime::GetTicks(ticks);
				particles[i][j]->setLifeTime(ticks);
				particles[i][j]->Update(ticks);
			}
		}
}

void InGameNormalModeArcade::Render(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor4ub(255, 255, 255, 255);
	glMatrixMode(GL_MODELVIEW);

	// Draw Main line
	//--------------------------------------------------------------
		glLoadIdentity();
		{
			glTexCoordPointer(2, GL_FLOAT, 0, boundaryLinesTextureCoords);
			glBindTexture(GL_TEXTURE_2D, lineTexture);
			glTranslatef(transX, 0, 0);
			glVertexPointer(2, GL_FLOAT, 0, mainLine);
			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
		}

	// Draw boundaries
	//--------------------------------------------------------------

		glLoadIdentity();
		{
			glTexCoordPointer(2, GL_FLOAT, 0, boundaryLinesTextureCoords);
			glTranslatef(transBoundariesX, 0, 0);
			glVertexPointer(2, GL_FLOAT, 0, boundaryLineLeft);
			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
		}

		glLoadIdentity();
		{
			glTexCoordPointer(2, GL_FLOAT, 0, boundaryLinesTextureCoords);
			glTranslatef(transBoundariesX, 0, 0);
			glVertexPointer(2, GL_FLOAT, 0, boundaryLineRight);
			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
		}

	// Draw trail
	//--------------------------------------------------------------

		float transRightX = (transX + 1.0f);
		if (direction == DIR_LEFT)
		{
			transRightX = (2.0f - transRightX) + 2.0f;
		}
		transRightX -= 1.0f;

		float transLeftX = (transX + 1.0f);
		if (direction == DIR_RIGHT)
		{
			transLeftX = -transLeftX;
		}
		transLeftX -= 1.0f;

		glLoadIdentity();
		{
			glTexCoordPointer(2, GL_FLOAT, 0, boundaryLinesTextureCoords);
			glBindTexture(GL_TEXTURE_2D, lineGradientTexture);
			glTranslatef(transRightX, 0, 0);
			glVertexPointer(2, GL_FLOAT, 0, lineGradient);
			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
		}

		glLoadIdentity();
		{
			glTexCoordPointer(2, GL_FLOAT, 0, boundaryLinesTextureCoords);
			glBindTexture(GL_TEXTURE_2D, lineGradientTexture);
			glTranslatef(transLeftX, 0, 0);
			glVertexPointer(2, GL_FLOAT, 0, lineLeftGradient);
			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
		}

	// Draw particles
	//--------------------------------------------------------------

		glLoadIdentity();
		{
			glBindTexture(GL_TEXTURE_2D, lineTexture);

			for(int i = 0; i < VERTICAL_PARTICLE_COUNT; i++)
				for(int j = 0; j < HORIZONTAL_PARTICLE_COUNT; j++)
				{
					if (particles[i][j] && particles[i][j]->life)
					{
						long long ticks;
						Osp::System::SystemTime::GetTicks(ticks);
						DrawParticles(i, j, ticks);
					}
				}
		}

	// Draw lightning
	//--------------------------------------------------------------
		glLoadIdentity();
		{
			glDisable(GL_TEXTURE_2D);

			for(int i = 0; i < NUM_LIGHTNINGS_BOUNDARIES; i++)
			{
				//lightYStart = (-BOUNDARY_HEIGHT / 2) + (BOUNDARY_HEIGHT * (float)(Math::Rand() % 11) / 10);
				//lightYEnd = (-BOUNDARY_HEIGHT / 2) + (BOUNDARY_HEIGHT * (float)(Math::Rand() % 11) / 10);
//				lightnings->drawLightning
//				(
//						transBoundariesX - 0.1,
//						lightYStart,
//						transBoundariesX + 0.1,
//						lightYEnd,
//						10
//				);
				glColor4f(1.0f, 1.0f, 1.0f, (float)(Math::Rand() % 11) / 10);
				lightnings->drawLightning
				(
						transBoundariesX - 0.1, -BOUNDARY_HEIGHT / 2,
						transBoundariesX - 0.1, +BOUNDARY_HEIGHT / 2,
						20
				);

				glColor4f(1.0f, 1.0f, 1.0f, (float)(Math::Rand() % 11) / 10);
				lightnings->drawLightning
				(
						transBoundariesX + 0.1, -BOUNDARY_HEIGHT / 2,
						transBoundariesX + 0.1, +BOUNDARY_HEIGHT / 2,
						20
				);
			}

			glEnable(GL_TEXTURE_2D);
		}
}

void InGameNormalModeArcade::DrawParticles(int i, int j, long long ticks)
{
	GLfloat alpha = 1.0f - (ticks - particles[i][j]->creationTime) / (GLfloat)particles[i][j]->lifetime;
	glColor4f(1,1,1,alpha);

	//Particles from left boundary
	glLoadIdentity();
	glTexCoordPointer(2, GL_FLOAT, 0, particles[i][j]->texCoords);
	glTranslatef(
			(oldTransBoundariesX - 0.1 - BOUNDARY_WIDTH / 2) + particles[i][j]->offsetX,
			(- BOUNDARY_HEIGHT / 2) + particles[i][j]->offsetY,
			0
	);
	glVertexPointer(2, GL_FLOAT, 0, particles[i][j]->vertArray);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

	//Particles from right boundary
	glLoadIdentity();
	glTexCoordPointer(2, GL_FLOAT, 0, particles[i][j]->texCoords);
	glTranslatef(
			(oldTransBoundariesX + 0.1 + BOUNDARY_WIDTH / 2) + particles[i][j]->offsetX,
			(- BOUNDARY_HEIGHT / 2) + particles[i][j]->offsetY,
			0
	);
	glVertexPointer(2, GL_FLOAT, 0, particles[i][j]->vertArray);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

}

void InGameNormalModeArcade::PointerPressed(float x, float y)
{
	needsNextBoundaries = true;
}

void InGameNormalModeArcade::NavigateBack()
{
	HitTheLines::getInstance()->PopScreen();
}

void InGameNormalModeArcade::CleanUp()
{
	AppLog("CleanUp start");
	for(int i = 0; i < VERTICAL_PARTICLE_COUNT; i++)
		for(int j = 0; j < HORIZONTAL_PARTICLE_COUNT; j++)
		{
			delete particles[i][j];
		}
	glDeleteTextures(1, &lineTexture);
	glDeleteTextures(1, &lineGradientTexture);

	AppLog("CeanUp end");
}

std::string InGameNormalModeArcade::GetScreenName()
{
	std::string name = "InGameNormalModeArcade";
	return name;
}

